library(stringr)
Warning messages:
1: replacing previous import ‘lifecycle::last_warnings’ by ‘rlang::last_warnings’ when loading ‘tibble’
2: replacing previous import ‘lifecycle::last_warnings’ by ‘rlang::last_warnings’ when loading ‘pillar’
library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
method from
print.tbl_lazy
print.tbl_sql
Warning: replacing previous import ‘lifecycle::last_warnings’ by ‘rlang::last_warnings’ when loading ‘hms’── Attaching packages ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse 1.3.1 ──
✔ ggplot2 3.3.4 ✔ purrr 0.3.4
✔ tibble 3.1.2 ✔ dplyr 1.0.7
✔ tidyr 1.1.3 ✔ forcats 0.5.1
✔ readr 1.4.0
── Conflicts ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
library(bigrquery)
library(MuMIn)
library(ggplot2)
library(ggpubr)
Registered S3 method overwritten by 'data.table':
method from
print.data.table
Registered S3 methods overwritten by 'car':
method from
influence.merMod lme4
cooks.distance.influence.merMod lme4
dfbeta.influence.merMod lme4
dfbetas.influence.merMod lme4
response <- try(system('~/google-cloud-sdk/bin/gcloud projects list --quiet', intern = T))
projectid <- strsplit(response[2], " ")[[1]][1]
options(na.action = "na.fail")
source("./helper__dredge_functions.R")
Loading required package: Matrix
Attaching package: ‘Matrix’
The following objects are masked from ‘package:tidyr’:
expand, pack, unpack
Attaching package: ‘scales’
The following object is masked from ‘package:purrr’:
discard
The following object is masked from ‘package:readr’:
col_factor
| Trophic Niche Accumulation |
accumulation <- read_csv('species_analysis__input__trophic_niche_accumulation.csv')
── Column specification ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
trophic_niche = col_character(),
percent = col_double(),
merlin_niche_count = col_double(),
merlin_remaining_species = col_logical(),
birdlife_niche_count = col_double(),
birdlife_remaining_species = col_logical()
)
accumulation
merlin_accumulation = ggplot(accumulation, aes(x = percent, y = merlin_niche_count)) +
geom_line(linetype = "dotted") +
geom_line(aes(linetype = merlin_remaining_species), na.value = "dash") +
scale_linetype_manual(values=c("blank", "solid"), guide = "none") +
geom_hline(data = . %>% group_by(trophic_niche) %>% filter(merlin_niche_count == max(merlin_niche_count)), aes(yintercept = merlin_niche_count), color = "blue", size = 0.25, linetype = "dashed") +
theme_bw() +
theme(legend.position = "bottom", strip.text = element_text(size = 6), axis.text.x = element_text(angle = 90, size = 6), axis.text.y = element_text(size = 6)) +
facet_wrap (~ trophic_niche) +
xlab("Percentage of all Species") +
ylab("Number of Niches") +
labs(title = "Merlin Niche Accumulation")
Warning: Ignoring unknown parameters: na.value
merlin_accumulation

birdlife_accumulation = ggplot(accumulation, aes(x = percent, y = birdlife_niche_count)) +
geom_line(linetype = "dotted") +
geom_line(aes(linetype = birdlife_remaining_species), na.value = "dash") +
scale_linetype_manual(values=c("blank", "solid"), guide = "none") +
geom_hline(data = . %>% group_by(trophic_niche) %>% filter(birdlife_niche_count == max(birdlife_niche_count)), aes(yintercept = birdlife_niche_count), color = "blue", size = 0.25, linetype = "dashed") +
theme_bw() +
theme(legend.position = "bottom", strip.text = element_text(size = 6), axis.text.x = element_text(angle = 90, size = 6), axis.text.y = element_text(size = 6)) +
facet_wrap (~ trophic_niche) +
xlab("Percentage of all Species") +
ylab("Number of Niches") +
labs(title = "Birdlife Niche Accumulation")
Warning: Ignoring unknown parameters: na.value
birdlife_accumulation

by_max_birdlife_niche_count = accumulation %>% group_by(trophic_niche) %>% summarise(Value = max(birdlife_niche_count))
by_max_birdlife_niche_count[order(-by_max_birdlife_niche_count$Value),]
ggplot(accumulation, aes(x = percent, y = merlin_niche_count)) +
geom_line(linetype = "dotted") +
geom_line(aes(linetype = birdlife_remaining_species), na.value = "dash") +
scale_linetype_manual(values=c("blank", "solid"), guide = "none") +
geom_hline(data = . %>% group_by(trophic_niche) %>% filter(merlin_niche_count == max(merlin_niche_count)), aes(yintercept = merlin_niche_count), color = "blue", size = 0.25, linetype = "dashed") +
theme_bw() +
theme(legend.position = "bottom", strip.text = element_text(size = 6), axis.text.x = element_text(angle = 90, size = 6), axis.text.y = element_text(size = 6)) +
facet_wrap (~ factor(trophic_niche, levels = c("Invertivore", "Aquatic predator", "Omnivore", "Vertivore", "Frugivore", "Herbivore aquatic", "Granivore", "Herbivore terrestrial", "Nectarivore", "Scavenger")), scales = "free") +
xlab("Percentage of total species\nordered by decreasing urban tolerance") +
ylab("Number of niches") +
xlim(40, 0)
Warning: Ignoring unknown parameters: na.value
ggsave("species_analysis__output__trophic_niche_accumlation_merlin.jpg")
Saving 7.29 x 4.51 in image

ggplot(accumulation, aes(x = percent, y = birdlife_niche_count)) +
geom_line(linetype = "dotted") +
geom_line(aes(linetype = birdlife_remaining_species), na.value = "dash") +
scale_linetype_manual(values=c("blank", "solid"), guide = "none") +
geom_hline(data = . %>% group_by(trophic_niche) %>% filter(birdlife_niche_count == max(birdlife_niche_count)), aes(yintercept = birdlife_niche_count), color = "blue", size = 0.25, linetype = "dashed") +
theme_bw() +
theme(legend.position = "bottom", strip.text = element_text(size = 6), axis.text.x = element_text(angle = 90, size = 6), axis.text.y = element_text(size = 6)) +
facet_wrap (~ factor(trophic_niche, levels = c("Invertivore", "Aquatic predator", "Omnivore", "Vertivore", "Frugivore", "Herbivore aquatic", "Granivore", "Herbivore terrestrial", "Nectarivore", "Scavenger")), scales = "free") +
xlab("Percentage of total species\nordered by decreasing urban tolerance") +
ylab("Number of niches") +
xlim(40, 0)
Warning: Ignoring unknown parameters: na.value
ggsave("species_analysis__output__trophic_niche_accumlation_birdlife.jpg")
Saving 7.29 x 4.51 in image

urban_niche_counts <- read_csv("species_analysis__input__birdlife_urban_niche_counts.csv")
── Column specification ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
trophic_niche = col_character(),
urban_niche_count = col_double()
)
urban_niche_counts
| Results table for number of urban niches |
birdlife_compare_counts <- accumulation[accumulation$percent == 100, c("trophic_niche", "birdlife_niche_count")]
names(birdlife_compare_counts) <- c("trophic_niche", "total_niche_count")
birdlife_compare_counts$trophic_niche <- factor(birdlife_compare_counts$trophic_niche)
birdlife_compare_counts
niche_count_data <- right_join(birdlife_compare_counts, urban_niche_counts)
Joining, by = "trophic_niche"
niche_count_data$total_percent_urban <- niche_count_data$urban_niche_count / niche_count_data$total_niche_count
niche_count_data
write_csv(niche_count_data, "species_analysis__output__niche_accumulation_results.csv")
| Explore taxonomic families |
urbanite_families <- read_csv('species_analysis__input__urbanite_taxonomic_families.csv')
── Column specification ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
taxonomic_family = col_character(),
birdlife_city_count = col_double(),
birdlife_pool_count = col_double(),
merlin_city_count = col_double(),
merlin_pool_count = col_double(),
birdlife_city_ratio = col_double(),
merlin_city_ratio = col_double()
)
urbanite_families
nrow(urbanite_families)
[1] 107
families_ordered_by_birdlife <- urbanite_families$taxonomic_family[order(urbanite_families$birdlife_city_ratio)]
urbanite_families$taxonomic_family = factor(urbanite_families$taxonomic_family, levels=families_ordered_by_birdlife)
ggplot(urbanite_families, aes(y = birdlife_city_ratio * 100, x = taxonomic_family)) +
geom_point() +
ylab("Percentage of cities\npresent when in\nregional pool") + xlab("Taxonomic Family") +
theme_bw() +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1, size=5))

ggsave("species_analysis__output__birdlife_taxonmic_families.jpg")
Saving 12 x 7.42 in image
families_ordered_by_merlin <- urbanite_families$taxonomic_family[order(urbanite_families$merlin_city_ratio)]
urbanite_families$taxonomic_family = factor(urbanite_families$taxonomic_family, levels=families_ordered_by_merlin)
ggplot(urbanite_families, aes(y = merlin_city_ratio * 100, x = taxonomic_family)) +
geom_col( alpha = .2) +
ylab("") + xlab("") +
theme_bw() +
#theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1, size=5)) +
theme(axis.text.x = element_text(angle = 360/(2*pi) * rev( pi/2 + seq( pi/155, 2*pi-pi/155, len=155)))) +
theme(panel.border = element_blank(),
legend.key = element_blank(),
axis.ticks = element_blank(),
axis.text.y = element_blank()) +
coord_polar(clip = "off")
Warning: Vectorized input to `element_text()` is not officially supported.
Results may be unexpected or may change in future versions of ggplot2.

ggsave("species_analysis__output__merlin_taxonmic_families.jpg")
Saving 12 x 16 in image
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKCmBgYHtyIHNldHVwfQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGJpZ3JxdWVyeSkKbGlicmFyeShNdU1JbikKbGlicmFyeShnZ3Bsb3QyKQoKbGlicmFyeShnZ3B1YnIpCgpyZXNwb25zZSA8LSB0cnkoc3lzdGVtKCd+L2dvb2dsZS1jbG91ZC1zZGsvYmluL2djbG91ZCBwcm9qZWN0cyBsaXN0IC0tcXVpZXQnLCBpbnRlcm4gPSBUKSkKcHJvamVjdGlkIDwtIHN0cnNwbGl0KHJlc3BvbnNlWzJdLCAiICIpW1sxXV1bMV0KCm9wdGlvbnMobmEuYWN0aW9uID0gIm5hLmZhaWwiKSAKCnNvdXJjZSgiLi9oZWxwZXJfX2RyZWRnZV9mdW5jdGlvbnMuUiIpCmBgYAoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpUcm9waGljIE5pY2hlIEFjY3VtdWxhdGlvbgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpgYGB7cn0KYWNjdW11bGF0aW9uIDwtIHJlYWRfY3N2KCdzcGVjaWVzX2FuYWx5c2lzX19pbnB1dF9fdHJvcGhpY19uaWNoZV9hY2N1bXVsYXRpb24uY3N2JykKYWNjdW11bGF0aW9uCmBgYApgYGB7cn0KbWVybGluX2FjY3VtdWxhdGlvbiA9IGdncGxvdChhY2N1bXVsYXRpb24sIGFlcyh4ID0gcGVyY2VudCwgeSA9IG1lcmxpbl9uaWNoZV9jb3VudCkpICsgCiAgZ2VvbV9saW5lKGxpbmV0eXBlID0gImRvdHRlZCIpICsgCiAgZ2VvbV9saW5lKGFlcyhsaW5ldHlwZSA9IG1lcmxpbl9yZW1haW5pbmdfc3BlY2llcyksIG5hLnZhbHVlID0gImRhc2giKSArCiAgc2NhbGVfbGluZXR5cGVfbWFudWFsKHZhbHVlcz1jKCJibGFuayIsICJzb2xpZCIpLCBndWlkZSA9ICJub25lIikgKwogIGdlb21faGxpbmUoZGF0YSA9IC4gJT4lIGdyb3VwX2J5KHRyb3BoaWNfbmljaGUpICU+JSBmaWx0ZXIobWVybGluX25pY2hlX2NvdW50ID09IG1heChtZXJsaW5fbmljaGVfY291bnQpKSwgYWVzKHlpbnRlcmNlcHQgPSBtZXJsaW5fbmljaGVfY291bnQpLCBjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDAuMjUsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNiksIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHNpemUgPSA2KSwgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA2KSkgKwogIGZhY2V0X3dyYXAgKH4gdHJvcGhpY19uaWNoZSkgKwogIHhsYWIoIlBlcmNlbnRhZ2Ugb2YgYWxsIFNwZWNpZXMiKSArIAogIHlsYWIoIk51bWJlciBvZiBOaWNoZXMiKSArCiAgbGFicyh0aXRsZSA9ICJNZXJsaW4gTmljaGUgQWNjdW11bGF0aW9uIikKCm1lcmxpbl9hY2N1bXVsYXRpb24KYGBgCgoKYGBge3J9CmJpcmRsaWZlX2FjY3VtdWxhdGlvbiA9IGdncGxvdChhY2N1bXVsYXRpb24sIGFlcyh4ID0gcGVyY2VudCwgeSA9IGJpcmRsaWZlX25pY2hlX2NvdW50KSkgKyAKICBnZW9tX2xpbmUobGluZXR5cGUgPSAiZG90dGVkIikgKyAKICBnZW9tX2xpbmUoYWVzKGxpbmV0eXBlID0gYmlyZGxpZmVfcmVtYWluaW5nX3NwZWNpZXMpLCBuYS52YWx1ZSA9ICJkYXNoIikgKwogIHNjYWxlX2xpbmV0eXBlX21hbnVhbCh2YWx1ZXM9YygiYmxhbmsiLCAic29saWQiKSwgZ3VpZGUgPSAibm9uZSIpICsKICBnZW9tX2hsaW5lKGRhdGEgPSAuICU+JSBncm91cF9ieSh0cm9waGljX25pY2hlKSAlPiUgZmlsdGVyKGJpcmRsaWZlX25pY2hlX2NvdW50ID09IG1heChiaXJkbGlmZV9uaWNoZV9jb3VudCkpLCBhZXMoeWludGVyY2VwdCA9IGJpcmRsaWZlX25pY2hlX2NvdW50KSwgY29sb3IgPSAiYmx1ZSIsIHNpemUgPSAwLjI1LCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDYpLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBzaXplID0gNiksICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gNikpICsKICBmYWNldF93cmFwICh+IHRyb3BoaWNfbmljaGUpICsKICB4bGFiKCJQZXJjZW50YWdlIG9mIGFsbCBTcGVjaWVzIikgKyAKICB5bGFiKCJOdW1iZXIgb2YgTmljaGVzIikgKwogIGxhYnModGl0bGUgPSAiQmlyZGxpZmUgTmljaGUgQWNjdW11bGF0aW9uIikKCmJpcmRsaWZlX2FjY3VtdWxhdGlvbgpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KVG90YWwgbnVtYmVyIG9mIG5pY2hlcwotLS0tLS0tLS0tLS0tLS0tLS0tLS0tCmBgYHtyfQpieV9tYXhfYmlyZGxpZmVfbmljaGVfY291bnQgPSBhY2N1bXVsYXRpb24gJT4lIGdyb3VwX2J5KHRyb3BoaWNfbmljaGUpICU+JSBzdW1tYXJpc2UoVmFsdWUgPSBtYXgoYmlyZGxpZmVfbmljaGVfY291bnQpKQpieV9tYXhfYmlyZGxpZmVfbmljaGVfY291bnRbb3JkZXIoLWJ5X21heF9iaXJkbGlmZV9uaWNoZV9jb3VudCRWYWx1ZSksXQpgYGAKCmBgYHtyfQpnZ3Bsb3QoYWNjdW11bGF0aW9uLCBhZXMoeCA9IHBlcmNlbnQsIHkgPSBtZXJsaW5fbmljaGVfY291bnQpKSArIAogIGdlb21fbGluZShsaW5ldHlwZSA9ICJkb3R0ZWQiKSArIAogIGdlb21fbGluZShhZXMobGluZXR5cGUgPSBiaXJkbGlmZV9yZW1haW5pbmdfc3BlY2llcyksIG5hLnZhbHVlID0gImRhc2giKSArCiAgc2NhbGVfbGluZXR5cGVfbWFudWFsKHZhbHVlcz1jKCJibGFuayIsICJzb2xpZCIpLCBndWlkZSA9ICJub25lIikgKwogIGdlb21faGxpbmUoZGF0YSA9IC4gJT4lIGdyb3VwX2J5KHRyb3BoaWNfbmljaGUpICU+JSBmaWx0ZXIobWVybGluX25pY2hlX2NvdW50ID09IG1heChtZXJsaW5fbmljaGVfY291bnQpKSwgYWVzKHlpbnRlcmNlcHQgPSBtZXJsaW5fbmljaGVfY291bnQpLCBjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDAuMjUsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNiksIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHNpemUgPSA2KSwgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA2KSkgKwogIGZhY2V0X3dyYXAgKH4gZmFjdG9yKHRyb3BoaWNfbmljaGUsIGxldmVscyA9IGMoIkludmVydGl2b3JlIiwgIkFxdWF0aWMgcHJlZGF0b3IiLCAiT21uaXZvcmUiLCAiVmVydGl2b3JlIiwgIkZydWdpdm9yZSIsICJIZXJiaXZvcmUgYXF1YXRpYyIsICJHcmFuaXZvcmUiLCAiSGVyYml2b3JlIHRlcnJlc3RyaWFsIiwgIk5lY3Rhcml2b3JlIiwgIlNjYXZlbmdlciIpKSwgc2NhbGVzID0gImZyZWUiKSArCiAgeGxhYigiUGVyY2VudGFnZSBvZiB0b3RhbCBzcGVjaWVzXG5vcmRlcmVkIGJ5IGRlY3JlYXNpbmcgdXJiYW4gdG9sZXJhbmNlIikgKyAKICB5bGFiKCJOdW1iZXIgb2YgbmljaGVzIikgKwogIHhsaW0oNDAsIDApCgoKCmdnc2F2ZSgic3BlY2llc19hbmFseXNpc19fb3V0cHV0X190cm9waGljX25pY2hlX2FjY3VtbGF0aW9uX21lcmxpbi5qcGciKQpgYGAKYGBge3J9CmdncGxvdChhY2N1bXVsYXRpb24sIGFlcyh4ID0gcGVyY2VudCwgeSA9IGJpcmRsaWZlX25pY2hlX2NvdW50KSkgKyAKICBnZW9tX2xpbmUobGluZXR5cGUgPSAiZG90dGVkIikgKyAKICBnZW9tX2xpbmUoYWVzKGxpbmV0eXBlID0gYmlyZGxpZmVfcmVtYWluaW5nX3NwZWNpZXMpLCBuYS52YWx1ZSA9ICJkYXNoIikgKwogIHNjYWxlX2xpbmV0eXBlX21hbnVhbCh2YWx1ZXM9YygiYmxhbmsiLCAic29saWQiKSwgZ3VpZGUgPSAibm9uZSIpICsKICBnZW9tX2hsaW5lKGRhdGEgPSAuICU+JSBncm91cF9ieSh0cm9waGljX25pY2hlKSAlPiUgZmlsdGVyKGJpcmRsaWZlX25pY2hlX2NvdW50ID09IG1heChiaXJkbGlmZV9uaWNoZV9jb3VudCkpLCBhZXMoeWludGVyY2VwdCA9IGJpcmRsaWZlX25pY2hlX2NvdW50KSwgY29sb3IgPSAiYmx1ZSIsIHNpemUgPSAwLjI1LCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDYpLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBzaXplID0gNiksICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gNikpICsKICBmYWNldF93cmFwICh+IGZhY3Rvcih0cm9waGljX25pY2hlLCBsZXZlbHMgPSBjKCJJbnZlcnRpdm9yZSIsICJBcXVhdGljIHByZWRhdG9yIiwgIk9tbml2b3JlIiwgIlZlcnRpdm9yZSIsICJGcnVnaXZvcmUiLCAiSGVyYml2b3JlIGFxdWF0aWMiLCAiR3Jhbml2b3JlIiwgIkhlcmJpdm9yZSB0ZXJyZXN0cmlhbCIsICJOZWN0YXJpdm9yZSIsICJTY2F2ZW5nZXIiKSksIHNjYWxlcyA9ICJmcmVlIikgKwogIHhsYWIoIlBlcmNlbnRhZ2Ugb2YgdG90YWwgc3BlY2llc1xub3JkZXJlZCBieSBkZWNyZWFzaW5nIHVyYmFuIHRvbGVyYW5jZSIpICsgCiAgeWxhYigiTnVtYmVyIG9mIG5pY2hlcyIpICsKICB4bGltKDQwLCAwKQoKCgpnZ3NhdmUoInNwZWNpZXNfYW5hbHlzaXNfX291dHB1dF9fdHJvcGhpY19uaWNoZV9hY2N1bWxhdGlvbl9iaXJkbGlmZS5qcGciKQpgYGAKCgpgYGB7cn0KdXJiYW5fbmljaGVfY291bnRzIDwtIHJlYWRfY3N2KCJzcGVjaWVzX2FuYWx5c2lzX19pbnB1dF9fYmlyZGxpZmVfdXJiYW5fbmljaGVfY291bnRzLmNzdiIpCnVyYmFuX25pY2hlX2NvdW50cwpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpSZXN1bHRzIHRhYmxlIGZvciBudW1iZXIgb2YgdXJiYW4gbmljaGVzCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpgYGB7cn0KYmlyZGxpZmVfY29tcGFyZV9jb3VudHMgPC0gYWNjdW11bGF0aW9uW2FjY3VtdWxhdGlvbiRwZXJjZW50ID09IDEwMCwgYygidHJvcGhpY19uaWNoZSIsICJiaXJkbGlmZV9uaWNoZV9jb3VudCIpXQpuYW1lcyhiaXJkbGlmZV9jb21wYXJlX2NvdW50cykgPC0gYygidHJvcGhpY19uaWNoZSIsICJ0b3RhbF9uaWNoZV9jb3VudCIpCgpiaXJkbGlmZV9jb21wYXJlX2NvdW50cyR0cm9waGljX25pY2hlIDwtIGZhY3RvcihiaXJkbGlmZV9jb21wYXJlX2NvdW50cyR0cm9waGljX25pY2hlKQpiaXJkbGlmZV9jb21wYXJlX2NvdW50cwoKbmljaGVfY291bnRfZGF0YSA8LSByaWdodF9qb2luKGJpcmRsaWZlX2NvbXBhcmVfY291bnRzLCB1cmJhbl9uaWNoZV9jb3VudHMpCgoKbmljaGVfY291bnRfZGF0YSR0b3RhbF9wZXJjZW50X3VyYmFuIDwtIG5pY2hlX2NvdW50X2RhdGEkdXJiYW5fbmljaGVfY291bnQgLyBuaWNoZV9jb3VudF9kYXRhJHRvdGFsX25pY2hlX2NvdW50CgpuaWNoZV9jb3VudF9kYXRhCmBgYAoKYGBge3J9CndyaXRlX2NzdihuaWNoZV9jb3VudF9kYXRhLCAic3BlY2llc19hbmFseXNpc19fb3V0cHV0X19uaWNoZV9hY2N1bXVsYXRpb25fcmVzdWx0cy5jc3YiKQpgYGAKCgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpFeHBsb3JlIHRheG9ub21pYyBmYW1pbGllcwotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCmBgYHtyfQp1cmJhbml0ZV9mYW1pbGllcyA8LSByZWFkX2Nzdignc3BlY2llc19hbmFseXNpc19faW5wdXRfX3VyYmFuaXRlX3RheG9ub21pY19mYW1pbGllcy5jc3YnKQp1cmJhbml0ZV9mYW1pbGllcwpgYGAKCmBgYHtyfQpucm93KHVyYmFuaXRlX2ZhbWlsaWVzKQpgYGAKCmBgYHtyLCBmaWcud2lkdGggPSA2fQpmYW1pbGllc19vcmRlcmVkX2J5X2JpcmRsaWZlIDwtIHVyYmFuaXRlX2ZhbWlsaWVzJHRheG9ub21pY19mYW1pbHlbb3JkZXIodXJiYW5pdGVfZmFtaWxpZXMkYmlyZGxpZmVfY2l0eV9yYXRpbyldCnVyYmFuaXRlX2ZhbWlsaWVzJHRheG9ub21pY19mYW1pbHkgPSBmYWN0b3IodXJiYW5pdGVfZmFtaWxpZXMkdGF4b25vbWljX2ZhbWlseSwgbGV2ZWxzPWZhbWlsaWVzX29yZGVyZWRfYnlfYmlyZGxpZmUpCgogICAgICAgICAgICAgICAgICAKZ2dwbG90KHVyYmFuaXRlX2ZhbWlsaWVzLCBhZXMoeSA9IGJpcmRsaWZlX2NpdHlfcmF0aW8gKiAxMDAsIHggPSB0YXhvbm9taWNfZmFtaWx5KSkgKyAKICBnZW9tX3BvaW50KCkgKwogIHlsYWIoIlBlcmNlbnRhZ2Ugb2YgY2l0aWVzXG5wcmVzZW50IHdoZW4gaW5cbnJlZ2lvbmFsIHBvb2wiKSArIHhsYWIoIlRheG9ub21pYyBGYW1pbHkiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUsIGhqdXN0PTEsIHNpemU9NSkpIAoKZ2dzYXZlKCJzcGVjaWVzX2FuYWx5c2lzX19vdXRwdXRfX2JpcmRsaWZlX3RheG9ubWljX2ZhbWlsaWVzLmpwZyIpCmBgYApgYGB7ciwgZmlnLndpZHRoID0gNiwgZmlnLmhlaWdodCA9IDh9CmZhbWlsaWVzX29yZGVyZWRfYnlfbWVybGluIDwtIHVyYmFuaXRlX2ZhbWlsaWVzJHRheG9ub21pY19mYW1pbHlbb3JkZXIodXJiYW5pdGVfZmFtaWxpZXMkbWVybGluX2NpdHlfcmF0aW8pXQp1cmJhbml0ZV9mYW1pbGllcyR0YXhvbm9taWNfZmFtaWx5ID0gZmFjdG9yKHVyYmFuaXRlX2ZhbWlsaWVzJHRheG9ub21pY19mYW1pbHksIGxldmVscz1mYW1pbGllc19vcmRlcmVkX2J5X21lcmxpbikKCiAgICAgICAgICAgICAgICAgIApnZ3Bsb3QodXJiYW5pdGVfZmFtaWxpZXMsIGFlcyh5ID0gbWVybGluX2NpdHlfcmF0aW8gKiAxMDAsIHggPSB0YXhvbm9taWNfZmFtaWx5KSkgKyAKICBnZW9tX2NvbCggYWxwaGEgPSAuMikgKwogIHlsYWIoIiIpICsgeGxhYigiIikgKwogIHRoZW1lX2J3KCkgKwogICN0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSwgc2l6ZT01KSkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzYwLygyKnBpKSAqIHJldiggcGkvMiArIHNlcSggcGkvMTU1LCAyKnBpLXBpLzE1NSwgbGVuPTE1NSkpKSkgKwogIHRoZW1lKHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBjb29yZF9wb2xhcihjbGlwID0gIm9mZiIpCgpnZ3NhdmUoInNwZWNpZXNfYW5hbHlzaXNfX291dHB1dF9fbWVybGluX3RheG9ubWljX2ZhbWlsaWVzLmpwZyIpCmBgYAoKCgo=